using System;
using System.IO;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEditor;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Security.Cryptography;
using System.Linq;
public static class AssetHelper
{
    public static Dictionary<object, string> ObjectGUIDMap = new Dictionary<object, string>();
    public static Dictionary<string, string> CreateFileIDMap = new Dictionary<string, string>();
    public static Dictionary<UnityEngine.Object, string> FieldMap = new Dictionary<UnityEngine.Object, string>();
    public static Dictionary<UnityEngine.Object, string> ObjectIdMap = new Dictionary<UnityEngine.Object, string>();
    public static HashSet<string> ObjectIdHashSet = new HashSet<string>();
    public static void Init()
    {
        ObjectGUIDMap.Clear();
        CreateFileIDMap.Clear();
        FieldMap.Clear();
        ObjectIdMap.Clear();
        ObjectIdHashSet.Clear();
    }
    public static void RecursiveObject(GameObject gameObject, Action<GameObject> recursive)
    {
        recursive?.Invoke(gameObject);
        foreach (Transform trans in gameObject.transform)
        {
            RecursiveObject(trans.gameObject, recursive);
        }
    }
    public static JToken CreateIdJObject(int id)
    {
        JObject jObject = new JObject();
        jObject["__id__"] = id;
        return jObject;
    }
    public static void CreatePrefab(ExportSetting exportSetting, GameObject gameObject, JArray jArray)
    {
        var objlocalid = GetIdName(gameObject);
        gameObject.name = objlocalid;
        var exportPath = $"{exportSetting.ExportPath}/Prefab/{objlocalid}.prefab";
        var exportMetaPath = $"{exportPath}.meta";
        if (IsCreateFileSameTime(exportMetaPath) || !AssetHelper.IsCanOverride(exportSetting, exportPath))
        {
            return;
        }
        JToken nodeToken = exportSetting.CocosObjectConfig["cc.Node"].DeepClone();
        CreateGameObjectToken(nodeToken, gameObject);
        JToken prefabToken = jArray[1];
        prefabToken["_lpos"] = nodeToken["_lpos"].DeepClone();
        prefabToken["_lrot"] = nodeToken["_lrot"].DeepClone();
        prefabToken["_lscale"] = nodeToken["_lscale"].DeepClone();
        prefabToken["_euler"] = nodeToken["_euler"].DeepClone();

        var ccprefabmeta = exportSetting.CocosMetaConfig["prefab"].DeepClone();
        ccprefabmeta["uuid"] = GetObjectUUID(gameObject);
        ccprefabmeta["userData"]["syncNodeName"] = gameObject.name;
        foreach (var item in jArray)
        {
            if (item["_id"] != null)
            {
                item["_id"] = "";
            }
        }
        File.WriteAllText(exportPath, jArray.ToString());
        File.WriteAllText(exportMetaPath, ccprefabmeta.ToString());
        Debug.Log("创建Prefab成功！" + " " + jArray.ToString());
    }
    public static void CreateGltfAndMeta(ExportSetting ExportSetting, Mesh mesh)
    {
        string meshPath = AssetDatabase.GetAssetPath(mesh);
        string meshPathExtension = Path.GetExtension(meshPath);

        mesh.name = GetIdName(mesh);
        string objguid = AssetHelper.GetObjectUUID(mesh);
        var exportPath = $"{ExportSetting.ExportPath}/Mesh/{mesh.name}.glb";
        var exportMetaPath = $"{ExportSetting.ExportPath}/Mesh/{mesh.name}.glb.meta";

        if (IsCreateFileSameTime(exportMetaPath) || !AssetHelper.IsCanOverride(ExportSetting, exportPath))
        {
            return;
        }
        var gameObject = new GameObject(mesh.name);
        var tempMaterial = new Material(Shader.Find("Standard"));
        gameObject.AddComponent<MeshFilter>().sharedMesh = mesh;
        gameObject.AddComponent<MeshRenderer>().sharedMaterial = tempMaterial;

        GLTFExportMenu.ExportGLBSelected(exportPath, gameObject);
        var gltfMeta = ExportSetting.CocosMetaConfig["gltf"].DeepClone();
        gltfMeta["uuid"] = objguid;
        gltfMeta["subMetas"] = new JObject();
        var assetFinderMeshJarray = gltfMeta["userData"]["assetFinder"]["meshes"] as JArray;
        var assetFinderMaterialJarray = gltfMeta["userData"]["assetFinder"]["materials"] as JArray;
        var assetFinderSceneJarray = gltfMeta["userData"]["assetFinder"]["scenes"] as JArray;
        assetFinderMeshJarray.Clear();
        assetFinderMaterialJarray.Clear();
        assetFinderSceneJarray.Clear();

        var gltfmesh = ExportSetting.CocosMetaConfig["gltf-mesh"].DeepClone();
        var meshLocalId = GetLocalId(mesh);
        var meshId = GetMetaIdByName($"{mesh.name}.mesh");
        if (mesh.name.Contains("level1_iron"))
        {
            Debug.Log("NameId2" + " " + mesh.name + " " + meshId);
        }
        //AddMetaId(objguid, meshMetaId);
        gltfmesh["uuid"] = $"{objguid}@{meshId}";
        gltfmesh["id"] = meshId;
        gltfmesh["name"] = $"{mesh.name}.mesh";
        gltfmesh["userData"]["gltfIndex"] = assetFinderMeshJarray.Count;

        gltfMeta["subMetas"][meshId] = gltfmesh;

        assetFinderMaterialJarray.Add(gltfmesh["uuid"]);

        var gltfmaterial = ExportSetting.CocosMetaConfig["gltf-material"].DeepClone();
        var matLocalId = AssetHelper.GetMetaIdByName(gltfmaterial["name"].ToString());
        gltfmaterial["id"] = matLocalId;
        gltfmaterial["uuid"] = $"{objguid}@{matLocalId}";
        gltfmaterial["userData"]["gltfIndex"] = assetFinderMaterialJarray.Count;

        gltfMeta["subMetas"][AssetHelper.GetObjectUUID(tempMaterial)] = gltfmaterial;
        assetFinderMaterialJarray.Add(gltfmaterial["uuid"]);

        var gltfScene = ExportSetting.CocosMetaConfig["gltf-scene"].DeepClone();

        var objid = GetObjectUUID(gameObject, true);
        gltfScene["uuid"] = $"{objguid}@{objid}";

        gltfScene["id"] = $"{objid}";
        gltfScene["name"] = $"{gameObject.name}.prefab";
        gltfScene["userData"]["gltfIndex"] = assetFinderSceneJarray.Count;

        assetFinderSceneJarray.Add(gltfScene["uuid"]);
        gltfMeta["subMetas"][objid] = gltfScene;
        gltfMeta["userData"]["redirect"] = gltfScene["uuid"];
        Debug.Log(exportMetaPath + " " + gltfMeta.ToString());
        File.WriteAllText(exportMetaPath, gltfMeta.ToString());
        GameObject.DestroyImmediate(gameObject);
        Debug.Log($"导出mesh成功 {exportPath}");
    }
    public static void CreateGltfAndMeta(ExportSetting ExportSetting, GameObject gameObject)
    {
        string objguid = GetObjectUUID(gameObject);
        gameObject.name = GetIdName(gameObject);
        var exportPath = $"{ExportSetting.ExportPath}/Mesh/{gameObject.name}.glb";
        var exportMetaPath = $"{ExportSetting.ExportPath}/Mesh/{gameObject.name}.glb.meta";
        if (IsCreateFileSameTime(exportPath) || !AssetHelper.IsCanOverride(ExportSetting, exportPath))
        {
            return;
        }
        //AddMetaId(path, localid);
        var gltfMeta = ExportSetting.CocosMetaConfig["gltf"].DeepClone();
        gltfMeta["uuid"] = objguid;
        gltfMeta["subMetas"] = new JObject();
        var assetFinderMeshJarray = gltfMeta["userData"]["assetFinder"]["meshes"] as JArray;
        var assetFinderMaterialJarray = gltfMeta["userData"]["assetFinder"]["materials"] as JArray;
        var assetFinderSceneJarray = gltfMeta["userData"]["assetFinder"]["scenes"] as JArray;
        assetFinderMeshJarray.Clear();
        assetFinderMaterialJarray.Clear();
        assetFinderSceneJarray.Clear();
        var assets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(gameObject));
        var meshes = new List<Mesh>();
        foreach (var item in assets)
        {
            if (item is Mesh mesh)
            {
                meshes.Add(mesh);
            }
        }
        foreach (var item in assets)
        {
            switch (item)
            {
                case MeshFilter meshFilter:
                    var mesh = meshFilter.sharedMesh;
                    meshFilter.name = GetIdName(mesh);
                    if (meshes.IndexOf(mesh) == 0)
                    {
                        mesh.name = gameObject.name;
                    }
                    else
                    {
                        mesh.name = meshFilter.name;
                    }
                    var gltfmesh = ExportSetting.CocosMetaConfig["gltf-mesh"].DeepClone();

                    var meshId = GetMetaIdByName($"{mesh.name}.mesh");
                    if (mesh.name.Contains("level1_iron"))
                    {
                        Debug.Log("NameId3" + " " + mesh.name + " " + meshId);
                    }
                    //AddMetaId(objguid, meshLocalId);
                    gltfmesh["uuid"] = $"{objguid}@{meshId}";
                    gltfmesh["id"] = meshId;
                    gltfmesh["name"] = $"{mesh.name}.mesh";
                    gltfmesh["userData"]["gltfIndex"] = assetFinderMeshJarray.Count;

                    gltfMeta["subMetas"][meshId] = gltfmesh;
                    assetFinderMaterialJarray.Add(gltfmesh["uuid"]);
                    break;
                case Material material:
                    var gltfmaterial = ExportSetting.CocosMetaConfig["gltf-material"].DeepClone();
                    var matLocalId = AssetHelper.GetMetaIdByName(gltfmaterial["name"].ToString());
                    //AddMetaId(objguid, matLocalId);
                    gltfmaterial["id"] = matLocalId;
                    gltfmaterial["uuid"] = $"{objguid}@{matLocalId}";
                    gltfmaterial["userData"]["gltfIndex"] = assetFinderMaterialJarray.Count;

                    gltfMeta["subMetas"][matLocalId] = gltfmaterial;
                    assetFinderMaterialJarray.Add(gltfmaterial["uuid"]);
                    break;
            }
        }
        var gltfScene = ExportSetting.CocosMetaConfig["gltf-scene"].DeepClone();
        var scenelocalId = AssetHelper.GetMetaIdByName($"{gameObject.name}.prefab");
        gltfScene["uuid"] = $"{objguid}@{scenelocalId}";
        gltfScene["id"] = $"{scenelocalId}";
        gltfScene["name"] = $"{gameObject.name}.prefab";
        gltfScene["userData"]["gltfIndex"] = assetFinderSceneJarray.Count;

        assetFinderSceneJarray.Add(gltfScene["uuid"]);
        gltfMeta["subMetas"][gltfScene["id"].ToString()] = gltfScene;
        gltfMeta["userData"]["redirect"] = gltfScene["uuid"];

        GLTFExportMenu.ExportGLBSelected(exportPath, gameObject);
        File.WriteAllText(exportMetaPath, gltfMeta.ToString());
        Debug.Log($"导出mesh成功 {exportPath} {gltfMeta.ToString()}");
        return;
    }
    public static void CreateMaterial(ExportSetting ExportSetting, Material material)
    {
        var ccmaterial = ExportSetting.CocosObjectConfig["cc.Material"].DeepClone();
        var ccmaterialmeta = ExportSetting.CocosMetaConfig["material"].DeepClone();
        var matuuid = GetObjectUUID(material);
        ccmaterialmeta["uuid"] = matuuid;
        var idName = AssetHelper.GetIdName(material);
        var exportPath = $"{ExportSetting.ExportPath}/Material/{idName}.mtl";
        var exportPathMeta = $"{ExportSetting.ExportPath}/Material/{idName}.mtl.meta";

        ParseShader(ExportSetting, material, ccmaterial, ccmaterialmeta);
        if (IsCreateFileSameTime(idName) || !AssetHelper.IsCanOverride(ExportSetting, exportPath))
        {
            return;
        }
        File.WriteAllText(exportPath, ccmaterial.ToString());
        File.WriteAllText(exportPathMeta, ccmaterialmeta.ToString());
    }
    public static void ParseShader(ExportSetting exportSetting, Material material, JToken ccmaterial, JToken ccmaterialmeta)
    {
        var textureId = GetMetaIdByName("texture");
        var normalmapId = GetMetaIdByName("normalMap");
        var shaderNameMap = exportSetting.CocosShaderConfig["ShaderNameMap"];
        var shaderPropMap = exportSetting.CocosShaderConfig["ShaderPropMap"];
        var shaderName = material.shader.name;
        var shaderMapName = exportSetting.CocosShaderConfig["ShaderNameMap"][shaderName]?.ToString();
        if (shaderMapName == null)
        {
            shaderMapName = "Unlit";
        }
        var shaderProp = shaderPropMap[shaderName];
        if (shaderProp == null)
        {
            shaderProp = shaderPropMap["Unlit"];
        }
        ccmaterial["_effectAsset"]["__uuid__"] = exportSetting.CocosShaderConfig["DefalutEffectUUID"][shaderMapName];
        ccmaterial["_techIdx"] = int.Parse(shaderProp["_techIdx"].ToString());
        (ccmaterial["_defines"][0] as JObject).Remove("USE_ALBEDO_MAP");
        (ccmaterial["_props"][0] as JObject).Remove("mainTexture");
        switch (shaderMapName)
        {
            case "Standard":
                if (shaderProp["_Mode"] != null)
                {
                    var standardMode = material.GetInt("_Mode");
                    switch (standardMode)
                    {
                        case 0:
                            ccmaterial["_techIdx"] = 0;
                            break;
                        default:
                            ccmaterial["_techIdx"] = 1;
                            break;
                    }
                }
                if (shaderProp["_MainTex"] != null)
                {
                    var stmainTex = material.GetTexture(shaderProp["_MainTex"].ToString());
                    if (stmainTex != null)
                    {
                        ccmaterial["_defines"][0]["USE_ALBEDO_MAP"] = true;
                        ccmaterial["_props"][0]["mainTexture"] = TransforCCObject(stmainTex);
                        ccmaterial["_props"][0]["mainTexture"]["__uuid__"] = $"{GetObjectUUID(stmainTex)}@{textureId}";
                        CreateTexture(exportSetting, stmainTex as Texture2D);
                        var mainst = material.GetVector($"{shaderProp["_MainTex"].ToString()}_ST");
                        ccmaterial["_props"][0]["tilingOffset"] = TransforCCObject(new Vector4(mainst.x, mainst.y, mainst.z, mainst.w));
                    }
                }
                if (shaderProp["_Color"] != null)
                {
                    var stmainColor = material.GetColor(shaderProp["_Color"].ToString());
                    ccmaterial["_props"][0]["mainColor"] = TransforCCObject(stmainColor);
                }
                if (shaderProp["_BumpMap"] != null)
                {
                    var bumptex = material.GetTexture(shaderProp["_BumpMap"].ToString());
                    if (bumptex != null)
                    {
                        ccmaterial["_defines"][0]["USE_NORMAL_MAP"] = true;
                        ccmaterial["_props"][0]["normalMap"] = TransforCCObject(bumptex);
                        ccmaterial["_props"][0]["normalMap"]["__uuid__"] = $"{GetObjectUUID(bumptex)}@{normalmapId}";
                        CreateTexture(exportSetting, bumptex as Texture2D);
                    }
                    if (shaderProp["_BumpScale"] != null)
                    {
                        var bumpscale = material.GetFloat(shaderProp["_BumpScale"].ToString());
                        ccmaterial["_props"][0]["normalStrenth"] = bumpscale;
                    }
                }
                if (shaderProp["_Glossiness"] != null)
                {
                    var glossiness = material.GetFloat(shaderProp["_Glossiness"].ToString());
                    ccmaterial["_props"][0]["roughness"] = 1 - glossiness;
                }
                if (shaderProp["_Cutoff"] != null)
                {
                    ccmaterial["_defines"][0]["USE_ALPHA_TEST"] = true;
                    var cutoff = material.GetFloat(shaderProp["_Cutoff"].ToString());
                    ccmaterial["_props"][0]["alphaThreshold"] = cutoff;
                }
                break;
            case "Unlit":
                if (shaderProp["_MainTex"] != null)
                {
                    var stmainTex = material.GetTexture(shaderProp["_MainTex"].ToString());
                    if (stmainTex != null)
                    {
                        ccmaterial["_defines"][0]["USE_TEXTURE"] = true;
                        ccmaterial["_props"][0]["mainTexture"] = TransforCCObject(stmainTex);
                        ccmaterial["_props"][0]["mainTexture"]["__uuid__"] = $"{GetObjectUUID(stmainTex)}@{textureId}";
                        CreateTexture(exportSetting, stmainTex as Texture2D);
                        var mainst = material.GetVector($"{shaderProp["_MainTex"].ToString()}_ST");
                        ccmaterial["_props"][0]["tilingOffset"] = TransforCCObject(new Vector4(mainst[0], mainst[1], mainst[2], mainst[3]));
                    }
                }
                if (shaderProp["_Color"] != null)
                {
                    var stmainColor = material.GetColor(shaderProp["_Color"].ToString());
                    ccmaterial["_props"][0]["mainColor"] = TransforCCObject(stmainColor);
                }
                if (shaderProp["_Cutoff"] != null)
                {
                    ccmaterial["_defines"][0]["USE_ALPHA_TEST"] = true;
                    var cutoff = material.GetFloat(shaderProp["_Cutoff"].ToString());
                    ccmaterial["_props"][0]["alphaThreshold"] = cutoff;
                }
                break;
        }
    }
    public static void CreateTexture(ExportSetting ExportSetting, Texture2D texture)
    {
        var ccimageMeta = ExportSetting.CocosMetaConfig["image"].DeepClone();
        ccimageMeta["uuid"] = GetObjectUUID(texture);
        var assetPath = AssetDatabase.GetAssetPath(texture);
        var assetextension = Path.GetExtension(assetPath);
        var assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
        TextureImporter textureImporter = (TextureImporter)TextureImporter.GetAtPath(assetPath);

        var cctexturemeta = ExportSetting.CocosMetaConfig["texture"].DeepClone();
        cctexturemeta["name"] = "texture";
        var textlocalId = GetMetaIdByName(cctexturemeta["name"].ToString());
        cctexturemeta["displayName"] = texture.name;
        cctexturemeta["uuid"] = $"{ ccimageMeta["uuid"].ToString()}@{textlocalId}";
        cctexturemeta["id"] = textlocalId;
        cctexturemeta["anisotropy"] = texture.anisoLevel;
        cctexturemeta["userData"]["wrapModeS"] = TransforCCObject(texture.wrapModeU)["TextureWrapMode"].ToString();
        cctexturemeta["userData"]["wrapModeT"] = TransforCCObject(texture.wrapModeV)["TextureWrapMode"].ToString();

        cctexturemeta["userData"]["mipfilter"] = TransforCCObject(texture.filterMode)["FilterMode"].ToString();
        cctexturemeta["userData"]["imageUuidOrDatabaseUri"] = ccimageMeta["uuid"];
        ccimageMeta["userData"]["hasAlpha"] = texture.alphaIsTransparency;
        ccimageMeta["userData"]["type"] = "texture";
        ccimageMeta["userData"]["redirect"] = cctexturemeta["uuid"];
        switch (textureImporter.textureType)
        {
            case TextureImporterType.Default:
                ccimageMeta["subMetas"][textlocalId] = cctexturemeta;
                break;
            case TextureImporterType.NormalMap:
                var normallocalid = GetMetaIdByName("normalMap");
                cctexturemeta["name"] = "normalMap";
                cctexturemeta["displayName"] = texture.name;
                cctexturemeta["uuid"] = $"{ ccimageMeta["uuid"].ToString()}@{normallocalid}";
                cctexturemeta["id"] = normallocalid;

                ccimageMeta["userData"]["type"] = "normal map";
                ccimageMeta["userData"]["redirect"] = cctexturemeta["uuid"];
                cctexturemeta["subMetas"][normallocalid] = cctexturemeta;
                break;
            case TextureImporterType.Sprite:
                ccimageMeta["subMetas"][textlocalId] = cctexturemeta;
                break;
        }
        var idName = AssetHelper.GetIdName(texture);
        var exportPath = $"{ExportSetting.ExportPath}/Texture/{idName}{assetextension}";
        var exportMetaPath = $"{exportPath}.meta";
        if (IsCreateFileSameTime(exportMetaPath) || !AssetHelper.IsCanOverride(ExportSetting, exportPath))
        {
            return;
        }
        File.Copy($"{Environment.CurrentDirectory}/{assetPath}", exportPath, true);
        File.WriteAllText(exportMetaPath, ccimageMeta.ToString());
    }
    public static JToken TransforCCObject<T>(T t)
    {
        JToken jToken = null;
        switch (t)
        {
            case Vector2 vector2:
                jToken = new JObject();
                jToken["__type__"] = "cc.Vec2";
                jToken["x"] = vector2.x;
                jToken["y"] = vector2.y;
                break;
            case Vector3 vector3:
                jToken = new JObject();
                jToken["__type__"] = "cc.Vec3";
                jToken["x"] = vector3.x;
                jToken["y"] = vector3.y;
                jToken["z"] = vector3.z;
                break;
            case Vector4 vector4:
                jToken = new JObject();
                jToken["__type__"] = "cc.Vec4";
                jToken["x"] = vector4.x;
                jToken["y"] = vector4.y;
                jToken["z"] = vector4.z;
                jToken["w"] = vector4.w;
                break;
            case Quaternion quaternion:
                jToken = new JObject();
                jToken["__type__"] = "cc.Quat";
                jToken["x"] = quaternion.x;
                jToken["y"] = quaternion.y;
                jToken["z"] = quaternion.z;
                jToken["w"] = quaternion.w;
                break;
            case Color color:
                jToken = new JObject();
                jToken["__type__"] = "cc.Color";
                jToken["r"] = color.r * 255;
                jToken["g"] = color.g * 255;
                jToken["b"] = color.b * 255;
                jToken["a"] = color.a * 255;
                break;
            case Rect rect:
                jToken = new JObject();
                jToken["__type__"] = "cc.Rect";
                jToken["x"] = rect.x;
                jToken["y"] = rect.y;
                jToken["width"] = rect.width;
                jToken["height"] = rect.height;
                break;
            case FilterMode filterMode:
                jToken = new JObject();
                switch (filterMode)
                {
                    case FilterMode.Point:
                        jToken["FilterMode"] = "none";
                        break;
                    case FilterMode.Bilinear:
                        jToken["FilterMode"] = "linear";
                        break;
                    case FilterMode.Trilinear:
                        jToken["FilterMode"] = "nearest";
                        break;
                }
                break;
            case Material material:
                jToken = new JObject();
                jToken["__expectedType__"] = "cc.Material";
                break;
            case Texture2D texture2D:
                jToken = new JObject();
                jToken["__uuid__"] = "";
                jToken["__expectedType__"] = "cc.Texture2D";
                break;
            case TextureWrapMode textureWrapMode:
                jToken = new JObject();
                switch (textureWrapMode)
                {
                    case TextureWrapMode.Clamp:
                        jToken["TextureWrapMode"] = "clamp-to-edge";
                        break;
                    case TextureWrapMode.Repeat:
                        jToken["TextureWrapMode"] = "repeat";
                        break;
                    default:
                        jToken["TextureWrapMode"] = "mirrored-repeat";
                        break;
                }
                break;
            case GameObject gameObject:
                jToken = new JObject();
                jToken["__uuid__"] = "";
                jToken["__expectedType__"] = "cc.Prefab";
                break;
        }
        return jToken;
    }
    public static string ToHexString(this long number)
    {
        return BitConverter.ToString(BitConverter.GetBytes(number)).Replace("-", "").ToLower();
    }
    public static string ToHexString(this int number)
    {
        return BitConverter.ToString(BitConverter.GetBytes(Convert.ToInt32(number))).Replace("-", "").ToLower();
    }
    public static int GetLocalId(UnityEngine.Object unityObject)
    {
        PropertyInfo inspectorModeInfo =
    typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);

        SerializedObject serializedObject = new SerializedObject(unityObject);
        inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);

        SerializedProperty localIdProp =
            serializedObject.FindProperty("m_LocalIdentfierInFile");   //note the misspelling!

        int localId = localIdProp.intValue;
        return localId;
    }
    public static string GetObjectUUID(object obj, bool isSimply = false)
    {
        string uuid = "";
        if (ObjectGUIDMap.ContainsKey(obj))
        {
            uuid = ObjectGUIDMap[obj];
        }
        else
        {
            if (obj is UnityEngine.Object uobj)
            {
                string idName = GetIdName(uobj);
                string newGuid = GetStrMD5Hash(idName, 32);
                newGuid = IdHelper.GetFormartId(newGuid);
                ObjectGUIDMap[obj] = newGuid;
                //}
            }
            else
            {
                ObjectGUIDMap[obj] = Guid.NewGuid().ToString();
            }
            uuid = ObjectGUIDMap[obj];

        }
        if (isSimply)
        {
            uuid = uuid.Substring(0, 5);
        }
        return uuid;
    }
    public static string GetFileMD5Hash(string fileName)
    {
        try
        {
            FileStream file = new FileStream(fileName, FileMode.Open);
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(file);
            file.Close();

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }
        catch (Exception ex)
        {
            throw new Exception("GetMD5Hash() fail,error:" + ex.Message);
        }
    }
    public static string GetStrMD5Hash(string password, int bit)
    {
        MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
        byte[] hashedDataBytes;
        hashedDataBytes = md5Hasher.ComputeHash(Encoding.ASCII.GetBytes(password));
        StringBuilder tmp = new StringBuilder();
        foreach (byte i in hashedDataBytes)
        {
            tmp.Append(i.ToString("x2"));
        }
        if (bit == 16)
            return tmp.ToString().Substring(8, 16);
        else
        if (bit == 32) return tmp.ToString();//默认情况
        else return string.Empty;
    }
    //private static Dictionary<string, HashSet<string>> CreateSubMetaIDSet = new Dictionary<string, HashSet<string>>();
    private static int[] _extendIndex = new int[] { 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30 };
    public static string GetMetaIdByName(string metaName, int extend = 0)
    {
        var md5 = AssetHelper.GetStrMD5Hash(metaName, 32);
        var meshid = $"{md5[0]}{md5[6]}{md5[16]}{md5[25]}{md5[31]}";
        for (int i = 0; i < extend; i++)
        {
            meshid += md5[_extendIndex[i]].ToString();
        }
        return meshid;
    }
    public static bool IsCreateFileSameTime(string filepath)
    {
        if (filepath.Contains("level1_iron_345_0"))
        {
            Debug.Log("1234");
        }
        if (CreateFileIDMap.ContainsKey(filepath))
        {
            return true;
        }
        else
        {
            CreateFileIDMap[filepath] = filepath;
            return false;
        }
    }
    public static bool IsCanOverride(ExportSetting exportSetting, string path)
    {
        if (!exportSetting.IsOverride && File.Exists(path))
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    public static string GetIdName(UnityEngine.Object obj)
    {
        if (ObjectIdMap.ContainsKey(obj))
        {
            return ObjectIdMap[obj];
        }
        var objName = GetNameWithoutId(obj);
        var path = AssetDatabase.GetAssetPath(obj);
        var curDir = Application.dataPath.Substring(0, Application.dataPath.Length - 7).ToString();
        if (!string.IsNullOrEmpty(path) && Path.HasExtension(path))
        {
            path = $"{curDir}/{path}";
        }
        else
        {
            var typeName = obj.GetType().Name;
            path = $"{curDir}/Assets/{typeName}/{obj.GetInstanceID().ToString()}";
        }
        string md5Id = GetMetaIdByName(path);
        int extend = 1;
        while (ObjectIdHashSet.Contains(md5Id))
        {
            md5Id = GetMetaIdByName(path, extend++);
        }
        ObjectIdHashSet.Add(md5Id);
        objName = $"{objName}@{md5Id}";
        ObjectIdMap.Add(obj, objName);
        return ObjectIdMap[obj];
    }
    public static string GetNameWithoutId(UnityEngine.Object obj)
    {
        var objName = obj.name;
        if (string.IsNullOrEmpty(objName)) objName = obj.GetType().Name;
        int lastcount = objName.Contains("@") ? objName.IndexOf("@") : objName.Length;
        objName = objName.Substring(0, lastcount);
        return objName;
    }
    public static void DirectoryCreate(string path)
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }
    public static string GetPrefabFieldId(UnityEngine.Object obj)
    {
        if (!FieldMap.TryGetValue(obj, out string fieldid))
        {
            var prefagInfoName = $"{GetIdName(obj)}.prefabinfo";
            fieldid = IdHelper.GetCompressGuid(IdHelper.GetGuid(prefagInfoName));// IdHelper.GetCompressGuid(GetStrMD5Hash(prefagInfoName, 32));
            FieldMap.Add(obj, fieldid);
        }
        return fieldid;
    }
    public static void CreateGameObjectToken(JToken nodeToken, GameObject gameObject)
    {
        nodeToken["_name"] = gameObject.name;
        nodeToken["_active"] = gameObject.activeSelf;
        nodeToken["_id"] = IdHelper.GetCompressGuid();
        nodeToken["_lpos"] = AssetHelper.TransforCCObject(gameObject.transform.localPosition);
        nodeToken["_lrot"] = AssetHelper.TransforCCObject(gameObject.transform.localRotation);
        nodeToken["_lscale"] = AssetHelper.TransforCCObject(gameObject.transform.localScale);
        nodeToken["_lpos"]["x"] = -(float)nodeToken["_lpos"]["x"];

        if (gameObject.TryGetComponent<Light>(out Light light) || gameObject.TryGetComponent<Camera>(out Camera camera))
        {
            nodeToken["_lrot"]["x"] = -(float)nodeToken["_lrot"]["x"];
            nodeToken["_lrot"]["w"] = -(float)nodeToken["_lrot"]["w"];
            var tempQuat = new Quaternion((float)nodeToken["_lrot"]["x"], (float)nodeToken["_lrot"]["y"], (float)nodeToken["_lrot"]["z"], (float)nodeToken["_lrot"]["w"]);
            tempQuat *= Quaternion.Euler(0, 180, 0);
            nodeToken["_lrot"] = AssetHelper.TransforCCObject(tempQuat);
            nodeToken["_euler"] = AssetHelper.TransforCCObject(CCMathHelper.ToCCEuler(tempQuat));
        }
        else
        {
            nodeToken["_lrot"]["x"] = -(float)nodeToken["_lrot"]["x"];
            nodeToken["_lrot"]["w"] = -(float)nodeToken["_lrot"]["w"];
            var tempQuat = new Quaternion((float)nodeToken["_lrot"]["x"], (float)nodeToken["_lrot"]["y"], (float)nodeToken["_lrot"]["z"], (float)nodeToken["_lrot"]["w"]);
            nodeToken["_euler"] = AssetHelper.TransforCCObject(CCMathHelper.ToCCEuler(tempQuat));
        }
    }
    public static void AddPropertyGameObejct(ExportSetting ExportSetting, GameObject prefabroot, GameObject gameObject, JArray jArray, JToken nodeToken)
    {
        var ccprefabinfo = ExportSetting.CocosObjectConfig["cc.PrefabInfo"].DeepClone();
        jArray.Add(ccprefabinfo);
        ccprefabinfo = jArray[jArray.Count - 1];
        ccprefabinfo["root"] = AssetHelper.CreateIdJObject(jArray.Count - 2);
        ccprefabinfo["fileId"] = GetPrefabFieldId(prefabroot);

        ccprefabinfo["asset"] = AssetHelper.TransforCCObject(gameObject);
        ccprefabinfo["asset"]["__uuid__"] = $"{AssetHelper.GetObjectUUID(prefabroot)}";
        ccprefabinfo["instance"] = AssetHelper.CreateIdJObject(jArray.Count);
        var ccprefabinstance = ExportSetting.CocosObjectConfig["cc.PrefabInstance"].DeepClone();
        jArray.Add(ccprefabinstance);
        ccprefabinstance = jArray[jArray.Count - 1];
        ccprefabinstance["fileId"] = IdHelper.GetCompressGuid();
        var propertyjarray = ccprefabinstance["propertyOverrides"] as JArray;
        propertyjarray.Clear();
        propertyjarray.Add(AssetHelper.CreateIdJObject(jArray.Count));
        var ccpropertyInfo = ExportSetting.CocosObjectConfig["CCPropertyOverrideInfo"].DeepClone();
        jArray.Add(ccpropertyInfo);
        ccpropertyInfo = jArray[jArray.Count - 1];
        ccpropertyInfo["propertyPath"][0] = "_name";
        ccpropertyInfo["value"] = gameObject.name;
        ccpropertyInfo["targetInfo"] = AssetHelper.CreateIdJObject(jArray.Count);

        var cctargeinfo = ExportSetting.CocosObjectConfig["cc.TargetInfo"].DeepClone();
        jArray.Add(cctargeinfo);
        cctargeinfo = jArray[jArray.Count - 1];
        cctargeinfo["localID"][0] = ccprefabinfo["fileId"];
        int targetIndex = jArray.Count - 1;

        //Debug.Log($"{prefabroot.transform.localPosition} {gameObject.transform.localPosition} {prefabroot.transform.localPosition != gameObject.transform.localPosition}");
        if (prefabroot.transform.localPosition != gameObject.transform.localPosition)
        {
            var prop = ExportSetting.CocosObjectConfig["CCPropertyOverrideInfo"].DeepClone();
            prop["propertyPath"][0] = "_lpos";
            prop["value"] = nodeToken["_lpos"].DeepClone();
            prop["targetInfo"] = AssetHelper.CreateIdJObject(targetIndex);
            propertyjarray.Add(AssetHelper.CreateIdJObject(jArray.Count));
            jArray.Add(prop);
        }
        //Debug.Log($"{prefabroot.transform.localRotation} {gameObject.transform.localRotation} {prefabroot.transform.localRotation != gameObject.transform.localRotation}");
        if (prefabroot.transform.localRotation != gameObject.transform.localRotation)
        {
            var prop = ExportSetting.CocosObjectConfig["CCPropertyOverrideInfo"].DeepClone();
            prop["propertyPath"][0] = "_lrot";
            prop["value"] = nodeToken["_lrot"].DeepClone();
            prop["targetInfo"] = AssetHelper.CreateIdJObject(targetIndex);
            propertyjarray.Add(AssetHelper.CreateIdJObject(jArray.Count));
            jArray.Add(prop);
        }
        //Debug.Log($"{prefabroot.transform.localScale} {gameObject.transform.localScale} {prefabroot.transform.localScale != gameObject.transform.localScale}");
        if (prefabroot.transform.localScale != gameObject.transform.localScale)
        {
            var prop = ExportSetting.CocosObjectConfig["CCPropertyOverrideInfo"].DeepClone();
            prop["propertyPath"][0] = "_lscale";
            prop["value"] = nodeToken["_lscale"].DeepClone();
            prop["targetInfo"] = AssetHelper.CreateIdJObject(targetIndex);
            propertyjarray.Add(AssetHelper.CreateIdJObject(jArray.Count));
            jArray.Add(prop);
        }
    }
}
